package com.railway.switchs.action.user;

import com.alibaba.excel.ExcelReader;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.metadata.Sheet;
import com.alibaba.excel.support.ExcelTypeEnum;
import com.railway.switchs.base.BaseResponse;
import com.railway.switchs.config.ExcelListener;
import com.railway.switchs.constant.FileConstant;
import com.railway.switchs.constant.SystemConstant;
import com.railway.switchs.domain.dto.authority.AuthorityRole;
import com.railway.switchs.domain.dto.user.UserInfo;
import com.railway.switchs.domain.pojo.user.UserInfoPojo;
import com.railway.switchs.domain.query.authority.AuthorityRoleQuery;
import com.railway.switchs.domain.query.user.UserInfoQuery;
import com.railway.switchs.domain.request.SendEmailRequest;
import com.railway.switchs.domain.response.FileUploadResponse;
import com.railway.switchs.domain.response.SendEmailResponse;
import com.railway.switchs.enums.EnumDateStyle;
import com.railway.switchs.enums.EnumReturnResult;
import com.railway.switchs.service.authority.IAuthorityRoleService;
import com.railway.switchs.service.message.ISendEmailService;
import com.railway.switchs.service.user.IUserInfoService;
import com.railway.switchs.utils.*;
import com.sun.org.apache.bcel.internal.generic.NEW;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @ClassName UserAction
 * @Author 魏梓晟
 * @Version 1.0
 **/
@Controller
@Slf4j
@RequestMapping("/back/admin")
public class UserAction {

    @Autowired
    private IUserInfoService userInfoService;

    @Autowired
    private IAuthorityRoleService authorityRoleService;

    @Autowired
    private ISendEmailService sendEmailService;

    /**
     * 进入用户列表页面
     * @return
     */
    @RequestMapping(value = "/list",method = RequestMethod.GET)
    public String list(){
        return "admin/list";
    }


    /**
     * 获取用户数据
     * @param query
     * @return
     */
    @ResponseBody
    @RequestMapping(value = "/getList",method = RequestMethod.POST)
    public UserInfoQuery getList(UserInfoQuery query) {
        try {
            query = userInfoService.query(query);
            query.setCode(EnumReturnResult.RETURN_200.getCode());
        } catch (Exception e) {
            log.error("获取用户列表数据异常", e);
            query.setCode(EnumReturnResult.RETURN_404.getCode());
            query.setCode("获取数据异常");
        }
        return query;
    }

    /**
     * 进入新增页面
     * @return
     */
    @RequestMapping(value = "/add",method = RequestMethod.GET)
    public String preAdd(){
        return "admin/add";
    }

    /**
     * 新增用户
     * @param userInfo
     * @param result
     * @return
     */
    @ResponseBody
    @RequestMapping(value = "/add",method = RequestMethod.POST)
    public BaseResponse add(@Validated UserInfo userInfo, BindingResult result){
        BaseResponse response = new BaseResponse();
        try{
            if(result.hasErrors()){
                response.setCode(EnumReturnResult.RETURN_404.getCode());
                response.setMsg("UserInfo-add参数有误");
                log.info("UserInfo-add参数有误："+result.getAllErrors().toString());
                return response;
            }
            //校验邮箱是否被注册
            if(StringUtil.isNotEmpty(userInfo.getUserEmail()) && !checkEmail(userInfo.getUserEmail())){
                response.setCode(EnumReturnResult.RETURN_404.getCode());
                response.setMsg("该邮箱已被注册");
                return response;
            }
            //系统生成账号
            String userAccount = CreateAccountUtil.createUserAccount(userInfo.getRoleCode().substring(0,1));
            //新增用户信息
            if(!saveUserInfo(userAccount,userInfo)){
                log.error("新增用户信息异常");
                response.setCode(EnumReturnResult.RETURN_404.getCode());
                response.setMsg("新增用户失败");
            }
            response.setCode(EnumReturnResult.RETURN_200.getCode());
            response.setMsg("新增用户成功");
        }catch (Exception e){
            log.error("新增用户异常",e);
            response.setCode(EnumReturnResult.RETURN_404.getCode());
            response.setMsg("新增用户失败");
        }
        return response;
    }

    /**
     * 进入用户信息修改页面
     * @param id
     * @return
     */
    @RequestMapping(value = "/edit",method = RequestMethod.GET)
    public ModelAndView preEdit(Long id){
        ModelAndView mav = new ModelAndView();
        try{
            UserInfo userInfo = userInfoService.get(id);
            mav.addObject("userInfo",userInfo);
            mav.setViewName("admin/edit");
        }catch (Exception e){
            log.error("获取用户详情失败",e);
            mav.addObject(SystemConstant.ERROR_KEY,"系统异常");
            mav.setViewName("admin/list");
        }
        return mav;
    }

    /**
     * 修改用户信息
     * @param userInfo
     * @return
     */
    @ResponseBody
    @RequestMapping(value = "edit",method = RequestMethod.POST)
    public BaseResponse edit(@Validated UserInfo userInfo, BindingResult result){
        BaseResponse response = new BaseResponse();
        try{
            if(result.hasErrors()){
                response.setCode(EnumReturnResult.RETURN_404.getCode());
                response.setMsg("UserInfo-edit参数有误");
                log.info("UserInfo-edit参数有误："+result.getAllErrors().toString());
                return response;
            }
            userInfoService.edit(userInfo);
            response.setCode(EnumReturnResult.RETURN_200.getCode());
            response.setMsg("修改用户信息成功");
        }catch (Exception e){
            log.error("修改用户信息失败",e);
            response.setCode(EnumReturnResult.RETURN_404.getCode());
            response.setMsg("修改用户信息失败");
        }
        return response;
    }

    /**
     * 重置密码
     * @param id
     * @return
     */
    @ResponseBody
    @RequestMapping(value = "/resetPassword",method = RequestMethod.POST)
    public BaseResponse resetPassword(Long id){
        BaseResponse response = new BaseResponse();
        try{
            UserInfo userInfo = userInfoService.get(id);
            String password = AuthorityUtil.createPassword();
            Map<String,String> passMap = Md5Util.encryption(password);
            if(StringUtil.isNotNull(passMap)){
                userInfo.setUserPassword(passMap.get("md5"));
                userInfo.setSalt(passMap.get("salt"));
                userInfoService.edit(userInfo);
                if(!sendPasswordToEmail(password,userInfo.getUserAccount(),userInfo)){
                    log.error("邮件发送用户密码失败");
                    response.setCode(EnumReturnResult.RETURN_404.getCode());
                    response.setMsg("重置密码失败");
                }
                response.setCode(EnumReturnResult.RETURN_200.getCode());
                response.setMsg("重置密码成功，新密码将通过邮件的形式发送！");
                return response;
            }
            response.setCode(EnumReturnResult.RETURN_404.getCode());
            response.setMsg("创建新密码异常");
        }catch (Exception e){
            log.error("重置密码失败",e);
            response.setCode(EnumReturnResult.RETURN_404.getCode());
            response.setMsg("重置密码失败");
        }
        return response;
    }

    /**
     * 删除用户
     * @param id
     * @return
     */
    @ResponseBody
    @RequestMapping(value = "/delete",method = RequestMethod.POST)
    public BaseResponse delete(Long id){
        BaseResponse response = new BaseResponse();
        try{
            userInfoService.delete(id);
            response.setCode(EnumReturnResult.RETURN_200.getCode());
            response.setMsg("删除用户成功");
        }catch (Exception e){
            log.error("删除用户异常",e);
            response.setCode(EnumReturnResult.RETURN_404.getCode());
            response.setMsg("删除用户失败");
        }
        return response;
    }

    /**
     * 获取用户数据
     * @param query
     * @return
     */
    @ResponseBody
    @RequestMapping(value = "/getAllList",method = RequestMethod.POST)
    public UserInfoQuery getAllList(UserInfoQuery query) {
        try {
            query.setData(userInfoService.getList(query));
            query.setCode(EnumReturnResult.RETURN_200.getCode());
        } catch (Exception e) {
            log.error("获取用户数据异常", e);
            query.setCode(EnumReturnResult.RETURN_404.getCode());
            query.setCode("获取用户数据异常");
        }
        return query;
    }


    /**
     * 校验邮箱是否被注册
     * @param userEmail
     * @return
     */
    private boolean checkEmail(String userEmail) {
        UserInfoQuery userInfoQuery = new UserInfoQuery();
        userInfoQuery.setUserEmail(userEmail);
        List<UserInfo> userInfoList = userInfoService.getList(userInfoQuery);
        if(StringUtil.isNotEmpty(userInfoList)){
            return false;
        }
        return true;
    }

    /**
     * 新增用户信息
     * @param userAccount
     * @param userInfo
     */
    private boolean saveUserInfo(String userAccount, UserInfo userInfo) {
        userInfo.setUserAccount(userAccount);
        //生成密码
//        String randomPassword = AuthorityUtil.createPassword();
        String randomPassword = "123456";
        log.info(userAccount + "随机生成的密码为:" + randomPassword);
        Map<String,String> passMap = Md5Util.encryption(randomPassword);
        if(StringUtil.isNotNull(passMap)){
            userInfo.setUserPassword(passMap.get("md5"));
            userInfo.setSalt(passMap.get("salt"));
        }
        if(userInfoService.add(userInfo) > 0){
            //发送邮件
//            if(!sendPasswordToEmail(randomPassword,userAccount,userInfo)){
//                log.error("邮件发送用户密码失败");
//                return false;
//            }
            return true;
        }
        return false;
    }

    /**
     * 发送密码给邮箱
     * @param password
     * @param userAccount
     * @param userInfo
     * @return
     */
    private boolean sendPasswordToEmail(String password,String userAccount,UserInfo userInfo){
        Map<String,String> paramMap = new HashMap<>();
        paramMap.put("userPassword",password);
        paramMap.put("userAccount",userAccount);
        String emailContent = "尊敬的用户：\n" +
                "            感谢注册铁路道岔故障检测信息管理系统,您的初始密码为userPassword,请及时修改您的密码！\n" +
                "                                                                                                         铁路道岔故障检测信息管理部";
        String sendContent = EmailUtil.injectionParam(emailContent,paramMap);//注入参数
        SendEmailRequest sendEmailRequest = new SendEmailRequest();
        sendEmailRequest.setText(sendContent);
        sendEmailRequest.setHtmlText(false);
        sendEmailRequest.setTo(userInfo.getUserEmail());
        sendEmailRequest.setNickName(SystemConstant.REGITER_NICK_NAME);
        sendEmailRequest.setSubject(userAccount + "初始密码发送");
        SendEmailResponse response = sendEmailService.sendEmail(sendEmailRequest);
        if(EnumReturnResult.RETURN_200.equals(response.getCode())){
            return true;
        }
        return false;
    }

    /**
     * 导出用户列表
     * @param response
     * @param query
     * @throws IOException
     */
    @RequestMapping(value = "/exports")
    public void exports(HttpServletResponse response, UserInfoQuery query) throws IOException {
        ExcelWriter writer = null;
        OutputStream outputStream = response.getOutputStream();
        try {
            //添加响应头信息
            String fileName = URLEncoder.encode("用户列表" + DateUtil.DateToString(new Date(), EnumDateStyle.YYYYMMDDHHMMSS), "UTF-8");
            response.setHeader("Content-disposition", "attachment; filename=" + fileName + ".xls");
            response.setContentType("application/msexcel;charset=UTF-8");
            response.setHeader("Pragma", "No-cache");
            response.setHeader("Cache-Control", "no-cache");
            response.setDateHeader("Expires", 0);
            //实例化 ExcelWriter
            writer = new ExcelWriter(outputStream, ExcelTypeEnum.XLS, true);
            //实例化表单
            Sheet sheet = new Sheet(1, 2, UserInfoPojo.class);
            sheet.setSheetName("用户信息");
            //获取数据
            List<UserInfo> authorityRoles = userInfoService.getList(query);
            //输出
            writer.write(authorityRoles, sheet);
            writer.finish();
            outputStream.flush();
        }catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                response.getOutputStream().close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 导入用户数据
     * @param file
     * @param request
     * @return
     * @throws Exception
     */
    @ResponseBody
    @RequestMapping("/import")
    public FileUploadResponse singleFileUpload(@RequestParam("file") MultipartFile file, HttpServletRequest request)throws Exception{
        FileUploadResponse response = new FileUploadResponse();
        try{
            InputStream inputStream = file.getInputStream();
            ExcelListener listener = new ExcelListener();
            //传入参数
            ExcelReader excelReader = new ExcelReader(inputStream, ExcelTypeEnum.XLS, null, listener);
            //读取信息
            excelReader.read(new Sheet(1, 2, UserInfoPojo.class));
            List<Object> objList = listener.getDatas();
            for (Object obj : objList){
                UserInfoPojo userInfoPojo = (UserInfoPojo)obj;
                UserInfo userInfo = new UserInfo();
                if(!checkEmail(userInfoPojo.getUserEmail())){
                    response.setCode(FileConstant.FILE_UPLOAD_ERROR);
                    response.setMsg("用户信息中邮箱"+userInfoPojo.getUserEmail()+"已存在");
                    return response;
                }
                //校验角色代码和角色名称是否存在
                AuthorityRoleQuery authorityRoleQuery = new AuthorityRoleQuery();
                authorityRoleQuery.setRoleCode(userInfoPojo.getRoleCode());
                authorityRoleQuery.setRoleName(userInfoPojo.getRoleName());
                if(StringUtil.isEmpty(authorityRoleService.getList(authorityRoleQuery))){
                    response.setCode(FileConstant.FILE_UPLOAD_ERROR);
                    response.setMsg("用户信息中角色信息"+userInfoPojo.getRoleCode()+"{"+userInfoPojo.getRoleName()+"}不存在");
                    return response;
                }
                userInfo.setNickName(userInfoPojo.getNickName());
                userInfo.setUserName(userInfoPojo.getUserName());
                userInfo.setUserSex(userInfoPojo.getUserSex());
                userInfo.setUserEmail(userInfoPojo.getUserEmail());
                userInfo.setUserTel(userInfoPojo.getUserTel());
                userInfo.setAreaCode(userInfoPojo.getAreaCode());
                userInfo.setRoleCode(userInfoPojo.getRoleCode());
                userInfo.setRoleName(userInfoPojo.getRoleName());
                userInfo.setRoleName(userInfoPojo.getNickName());
                //生成系统账号
                String userAccount = CreateAccountUtil.createUserAccount(userInfoPojo.getRoleCode().substring(0,1));
                //生成密码和盐值
                if(!saveUserInfo(userAccount,userInfo)){
                    log.error("新增用户信息异常,index"+userInfoPojo.getUserName());
                }
            }
            response.setCode(FileConstant.FILE_UPLOAD_SUCCESS);
            response.setMsg("导入用户数据成功");
        }catch (Exception e){
            log.info("导入用户数据{}失败",file.getOriginalFilename());
            log.error("导入用户数据失败：",e);
            response.setCode(FileConstant.FILE_UPLOAD_ERROR);
            response.setMsg("导入用户数据异常");
        }
        return response;
    }
}
